package com.my.ycv51.ui;

import static com.cloudwalk.android.CWDefine.CWFaceQualityCode.CW_FACE_LIV_DEPTH_INTEGRITY_ERR;
import static com.cloudwalk.android.CWDefine.CWFaceQualityCode.CW_FACE_LIV_VIS_PUPIL_DIS_ERR;
import static com.cloudwalk.android.CWDefine.CWLDEnumCamType.CW_CAMERA_OPEN_ALL;
import static com.cloudwalk.android.CWDefine.CWLDEnumCamType.CW_CAMERA_OPEN_VIS;
import static com.cloudwalk.android.CWDefine.CWLivenessErrorCode.CW_LIVENESS_MULTI_FACE_ERROR;
import static com.cloudwalk.android.CWDefine.CW_SDK_SUCCESS;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.cloudwalk.android.CWCameraDataCallback;
import com.cloudwalk.android.CWDefine;
import com.cloudwalk.android.CWDetectCallback;
import com.cloudwalk.android.CWFaceRect;
import com.cloudwalk.android.CWFeature;
import com.cloudwalk.android.CWLDImage;
import com.cloudwalk.android.CWPathInfo;
import com.cloudwalk.android.CWRecogInfo;
import com.cloudwalk.android.CWRet;
import com.my.ycv51.R;
import com.my.ycv51.util.Change;
import com.my.ycv51.util.LogUtil;
import com.my.ycv51.util.ToastUtils;
import com.my.ycv51.ycinit.config.Constants;
import com.my.ycv51.ycinit.config.ErrorCode;
import com.my.ycv51.ycinit.impl.CWLiveEngine;
import com.my.ycv51.ycinit.mgr.CwStoreMgr;
import com.my.ycv51.ycinit.opengl.CWGLDisplay;
import com.my.ycv51.ycinit.opengl.GLFrameSurface;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public class MainActivity extends AppCompatActivity {
    private String TAG = "【云从】";
    private Button btnStart;
    private TextView tvTip;
    private GLFrameSurface surfaceView;

    /**
     * 连续活检状态
     */
    private static final AtomicBoolean isliveDetecting = new AtomicBoolean(false);
    /**
     * 云从视频显示参数设置
     */
    private CWGLDisplay mVisGLDisplay;

    //    private QrBarProvider mQrProvider;
    /**
     * 云从视频引擎
     */
    private CWLiveEngine mEngine;

    /**
     * 云从引擎日志（打印用）
     */
    private final CWLiveEngine.OnEngineInterfaceCallListener mOnEngineInterfaceCallListener = (String msg) -> refreshDebugApiView(msg);

    /**
     * 双目摄像头开启的种类
     */
    private CWDefine.CWLDEnumCamType camOpenType = CW_CAMERA_OPEN_ALL;
    /**
     * 权限 文件读写，相机
     */
    private String[] requirePermissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA};

    /**
     * 权限请求码
     */
    private static final int PERMISSION_REQUEST_CODE = 1000;

    /**
     * 流是否开启了
     */
    private final AtomicBoolean isStreamOn = new AtomicBoolean(false);

    private Handler mWorkHandler;
    private HandlerThread mWorkThread;

    /**
     * 相机是否初始化了
     */
    private boolean mHasInitCamera = false;

    /**
     * 面部识别锁
     */
    private final Object faceRecognizeLock = new Object();

    /**
     * 人脸识别模型路径
     */
    private static final String DEFAULT_MODEL_PATH = "/data/local/tmp/assets/";

    /**
     * 吐司
     */
    private static final int DISPLAY_TOAST_CODE = 1003;

    private CwStoreMgr.CameraOpenEntry cameraOpenEntry;

    private static final int DEFAULT_CAMERA_WIDTH = 640;

    private static final int DEFAULT_CAMERA_HEIGHT = 480;

    private static final int DEFAULT_CAMERA_FPS = 30;

    private final AtomicBoolean isFirstFrame = new AtomicBoolean(true);
    private volatile boolean isContinuity = false;

    /**
     * 单次检测
     * Single detect
     */
    private volatile static long singleDetectTime = 0;

//    private CwStoreMgr cwStoreMgr;

    private final CWFaceRect mLiveDetectRect = new CWFaceRect();

    private Handler mMainHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case DISPLAY_TOAST_CODE: // 吐司
                    String s = (String) msg.obj;
//                    Log.i(TAG, s);
//                    ToastUtils.toast(getApplicationContext(), s);
                    tvTip.setText(s);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initWorkHandlerThread();

        mEngine = CWLiveEngine.getInstance();

        initView();
        isliveDetecting.set(false);
        initListener();
    }

    private void initListener() {
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvTip.setText("");
                processStreamOnOff();
            }
        });

        findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }

    /**
     * Process stream on and  off
     */
    private void processStreamOnOff() {
        mWorkHandler.post(() -> {
            if (!mHasInitCamera) {
                runOnUiThread(() -> {
                    displayToast("初始化失败");
                });
                return;
            }
//            mStartStream = System.currentTimeMillis();
            if (!isStreamOn.get()) {
                startStream();
            } else {
                stopStream();
                if (surfaceView != null && surfaceView.getCurrentRenderer() != null) {
                    try {
                        surfaceView.getCurrentRenderer().clear();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            isContinuity = false;
            processDetectorUI();
        });
    }

    /**
     * Update detect ui.
     */
    private void processDetectorUI() {
        if (isContinuity) {

        } else {
            stopContinuityDetect();

        }
    }

    /**
     * Stop continuity detect
     */
    private void stopContinuityDetect() {
        mEngine.stopDetect();
        isliveDetecting.set(false);
    }

    /**
     * camera stream on.
     */

    private void startStream() {
        refreshDebugApiView("打开模组");
        isFirstFrame.set(true);
        CWRet ret = mEngine.cameraStreamOn(camOpenType, true);
        if (ret.errorCode != CWDefine.CW_SDK_SUCCESS) {
            displayToast("模组出流打开失败,Error: " + ret.errorCode);
        }
//        runOnUiThread(() -> {
//            mMainDisplayBinding.btnCameraOpenAndClose.setText("关闭模组");
//            mMainDisplayBinding.rlOpenAndCloseCamera.setBackgroundResource(R.drawable.shape_main_default_btn_red);
//            mMainDisplayBinding.tvDetectResult.setVisibility(View.VISIBLE);
//        });
        isStreamOn.set(true);
    }

    private void initWorkHandlerThread() {
        mWorkThread = new HandlerThread("WorkThread");
        mWorkThread.start();
        mWorkHandler = new Handler(mWorkThread.getLooper());
    }

    private void initView() {
        btnStart = findViewById(R.id.btn_start);
        surfaceView = findViewById(R.id.camera_surfaceview);
        tvTip = findViewById(R.id.tv_tip);

        mVisGLDisplay = new CWGLDisplay();
    }


    @Override
    protected void onResume() {
        super.onResume();

        long startTime = 0;
        if (startTime != 0) {
            refreshDebugApiView("Demo启动耗时：" + (System.currentTimeMillis() - startTime) + "ms");
        }

        loadAllConfig(); // 只设置了个回调，打印日志用 没什么用
//        processFaceMantle();
        processPermission(); // 请求权限
        setDetectorParameters(); // 没什么用

        mWorkHandler.post(new Runnable() {
            @Override
            public void run() {
                synchronized (faceRecognizeLock) {
                    if (mVisGLDisplay != null) {
                        mVisGLDisplay.setmIsDisplayStarted(false);
                    }
                }
            }
        });
    }

    /**
     * 设置监视器参数
     */
    private void setDetectorParameters() {
        if (!mEngine.isInitialized()) {
            return;
        }
    }

    /**
     * 请求权限
     */
    private void processPermission() {
        boolean allGranted = checkPermissionAllGranted(requirePermissions);

        if (!allGranted) {
            ActivityCompat.requestPermissions(this, requirePermissions, PERMISSION_REQUEST_CODE);
        } else {
            mWorkHandler.post(this::initSDK);
        }
    }

    /**
     * 初始化云从相机
     */
    private void initSDK() {
        // 停止检测
        mEngine.stopDetect();
        closeCamera();
        mEngine.unInit();
        CWPathInfo cwPathInfo = new CWPathInfo();
        cwPathInfo.setConfigurePath(DEFAULT_MODEL_PATH);
        cwPathInfo.setLicensePath(DEFAULT_MODEL_PATH);
        {
            //初始化SDK
            CWRet<Long> cwRet = mEngine.init(this.getApplicationContext(), cwPathInfo, CWDefine.CWLDEnumLiveMode.CW_LIVEMODE_AUTO, cameraOpenEntry.getOpenMode());
            if (CW_SDK_SUCCESS != cwRet.errorCode || cwRet.obj == null) {
                displayToast("SDK初始化失败 ErrorCode: " + cwRet.errorCode);
                return;
            }
            mEngine.setEventCallback(mCWLiveDetectCallback, null);
        }

        //打开相机
        CWRet cwRet = mEngine.openCamera(camOpenType);
        if (CW_SDK_SUCCESS != cwRet.errorCode) {
            displayToast("初始化失败 ErrorCode: " + cwRet.errorCode);
            refreshDebugApiView("初始化失败");
            return;
        }

        mHasInitCamera = true;
        setCameraCommonParameters();
        setDetectorParameters();

        LogUtil.e(TAG + "SDK初始化完毕" + cwRet.errorCode);

        if (!checkCWRetSucc(cwRet)) {
            LogUtil.e(TAG + "检测SDK初始化失败");
        } else {
            LogUtil.e(TAG + "检测SDK初始化成功");

            processStreamOnOff(); // 开启流
        }
    }

    /**
     * 设置相机公共参数
     */
    private void setCameraCommonParameters() {
        if (!mEngine.isInitialized() || !mHasInitCamera) {
            refreshDebugApiView("setCameraCommonParameters fail: camera not init");
            return;
        }
        CWRet cwRet = mEngine.setCameraRotateAndMirror(camOpenType, getCameraAngle(), getCameraMirror());
        if (!checkCWRetSucc(cwRet)) {
            displayToast("设置相机旋转镜像失败");
            refreshDebugApiView("setCameraRotateAndMirror " + cwRet.errorCode);
            return;
        }
        cwRet = mEngine.setCameraStreamFormat(camOpenType,
                CWDefine.CWEnumCameraStreamFormat.CW_CAMERA_STREAM_FORMAT_MJPEG, DEFAULT_CAMERA_WIDTH, DEFAULT_CAMERA_HEIGHT, DEFAULT_CAMERA_FPS);
        if (!checkCWRetSucc(cwRet)) {
            displayToast("设置相机出流参数失败");
            refreshDebugApiView("setCameraStreamFormat " + cwRet.errorCode);
            return;
        }
        cwRet = mEngine.setCameraDataCallback(camOpenType == CW_CAMERA_OPEN_ALL ? CW_CAMERA_OPEN_VIS : camOpenType,
                mCameraDataCallback,
                CWDefine.CWEnumCameraDataFormat.CW_CAMERA_FRAME_FORMAT_RGB888, true, null);
        if (!checkCWRetSucc(cwRet)) {
            displayToast("设置相机数据回调失败");
            refreshDebugApiView("setCameraDataCallback " + cwRet.errorCode);
            return;
        }
    }

    /**
     * 相机的回调
     */
    private final CWCameraDataCallback mCameraDataCallback = (cameraImage, cameraDevice, userParam) -> {

        if (isFirstFrame.get()) { //第一帧
            isFirstFrame.set(false);
            LogUtil.e(TAG + "第一帧");
            processLiveDetect(); // 执行活检
        }

        if ((surfaceView != null) && (mVisGLDisplay != null)) {
            int renderDataType = 1;
            final CWDefine.CWEnumCameraDataFormat format = CWDefine.CWEnumCameraDataFormat.values()[cameraImage.getFormat()];
            switch (format) {
                case CW_CAMERA_FRAME_FORMAT_YUV420: {
                    renderDataType = 0;
                    break;
                }
                case CW_CAMERA_FRAME_FORMAT_RGB888: {
                    renderDataType = 1;
                    break;
                }
                case CW_CAMERA_FRAME_FORMAT_GRAY8: {
                    renderDataType = 2;
                    break;
                }
                case CW_CAMERA_FRAME_FORMAT_GRAY16: {
                    renderDataType = 3;
                    break;
                }
            }

            mVisGLDisplay.render(surfaceView,
                    cameraImage.getAngle(),
                    cameraImage.getMirror() == 1,
                    cameraImage.getData(),
                    cameraImage.getWidth(),
                    cameraImage.getHeight(), renderDataType);

        }

//        processScan(cameraImage);
    };


    /**
     * 是否活检配置完成
     * Carry out live detect,when mLiveType is zero,execute once,when that is one ,execute always.
     */
    private volatile boolean isLiveDetectSeting = false;

    /**
     * 活检处理
     */
    private void processLiveDetect() {
        LogUtil.e(TAG + "处理活检");
        if (isLiveDetectSeting) {
            return;
        }
        mWorkHandler.post(() -> {
            if (isLiveDetectSeting) {
                return;
            }
            isLiveDetectSeting = true;
            if (!mEngine.isInitialized() || !mHasInitCamera) {
                displayToast("不满足活检条件");
                isLiveDetectSeting = false;
                return;
            }
            CWRet<CWDefine.CWEnumCameraStatus> cwRet = mEngine.getCameraStatus(camOpenType == CW_CAMERA_OPEN_ALL ? CW_CAMERA_OPEN_VIS : camOpenType);
            if (!checkCWRetSucc(cwRet) || cwRet.obj != CWDefine.CWEnumCameraStatus.CW_CAMERA_STATUS_STREAMON) {
                displayToast("请先开启模组");
                isLiveDetectSeting = false;
                return;
            }

            singleDetect();

            isLiveDetectSeting = false;
        });
    }

    /**
     * 单一活检
     */
    private void singleDetect() {
        LogUtil.e(TAG + "下发活检");
        if (!mEngine.isInitialized() || !mHasInitCamera) {
            LogUtil.e(TAG + "初始化null");
            return;
        }
//        mutDetectTime = 0;
        singleDetectTime = System.currentTimeMillis();
        // 下发活检关键代码
        CWRet cwRet = mEngine.startDetect(CWDefine.CWEnumDetectType.CW_DECTYPE_LIVENESS, 0);

        if (!checkCWRetSucc(cwRet)) { // 活检异常提示
            if (75003007 == cwRet.errorCode) {
                LogUtil.e(TAG + "正在活检中");
                displayToast("正在活检中");
            } else {
                displayToast("下发活检异常 Error: " + cwRet.errorCode);
                LogUtil.e("下发活检异常 Error: " + cwRet.errorCode);
            }
        }
    }

    private boolean checkCWRetSucc(CWRet cwRet) {
        return cwRet.errorCode == CW_SDK_SUCCESS;
    }

    /**
     * 相机预览角度
     *
     * @return
     */
    private CWDefine.CWEnumCameraDataAngle getCameraAngle() {
        return CWDefine.CWEnumCameraDataAngle.valueOf(0);
    }

    /**
     * 是否镜像 0不开启镜像，1开启镜像
     *
     * @return
     */
    private CWDefine.CWEnumCameraDataMirror getCameraMirror() {
        return CWDefine.CWEnumCameraDataMirror.values()[1];
    }

    /**
     * 吐司
     *
     * @param mMsg
     */
    private void displayToast(String mMsg) {
        if (!TextUtils.isEmpty(mMsg)) {
            Log.i(TAG, mMsg);
            Message message = Message.obtain();
            message.what = DISPLAY_TOAST_CODE;
            message.obj = mMsg;
            mMainHandler.sendMessage(message);
        }
    }

    /**
     * 关闭相机
     */
    private void closeCamera() {
        stopStream();
        mEngine.closeCamera(camOpenType);
        mHasInitCamera = false;
        if (surfaceView != null && surfaceView.getCurrentRenderer() != null) {
            surfaceView.getCurrentRenderer().clear();
        }
    }

    /**
     * camera stream off.
     */
    private void stopStream() {
        refreshDebugApiView("模组出流关闭");
        mEngine.cameraStreamOn(camOpenType, false);
        runOnUiThread(() -> {
            btnStart.setText("开启模组");
        });
        isStreamOn.set(false);
    }

    /**
     * 请求权限
     *
     * @param permissions
     * @return
     */
    private boolean checkPermissionAllGranted(String[] permissions) {
        if (permissions != null) {
            for (String permission : permissions) {
                if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 加载所有配置
     */
    private void loadAllConfig() {
        mEngine.addEngineInterfaceCallListener(mOnEngineInterfaceCallListener);
//        camOpenType = CW_CAMERA_OPEN_ALL;
//        cameraOpenEntry = cwStoreMgr.getCameraOpenEntry();
        cameraOpenEntry = new CwStoreMgr.CameraOpenEntry(1,
                Constants.DEFAULT_RGB_PID, Constants.DEFAULT_IR_PID, Constants.DEFAULT_RGB_VID, Constants.DEFAULT_IR_VID,
                true, true);
    }

    /**
     * 日志
     *
     * @param s
     */
    private void refreshDebugApiView(String s) {
        LogUtil.e(s);
    }

    // TODO MWB 新加人脸特征获取 mDisplayImage.setImage
    private final CWLDImage mDisplayImage = new CWLDImage();
    private final CWLDImage mLiveDetectImage = new CWLDImage();
    private final Object lockLiveDetect = new Object();

    /**
     * Live detect callback.
     */
    private CWDetectCallback mCWLiveDetectCallback = (errorCode, timestamp, cwLiveImage, cwDetectorCallbackData, userParam) -> {
        LogUtil.e("callback:" + errorCode);

        if (cwDetectorCallbackData == null) {
            Log.e(TAG, "cwDetectorCallbackData null");
            return;
        }
        switch (CWDefine.CWEventType.values()[cwDetectorCallbackData.getDetectEventType()]) {
            case CW_EVENT_FACE_DETECT: {
                singleDetect();
                break;
            }
            case CW_EVENT_LIVE_DETECT: {
                LogUtil.e(TAG + "CW_EVENT_LIVE_DETECT");
//                if (singleDetectTime != 0) {
//                    refreshDebugApiView("单次活检耗时: " + (System.currentTimeMillis() - singleDetectTime) + "ms");
//                    singleDetectTime = 0;
//                }

                if (errorCode == ErrorCode.CW_FACE_LIV_IS_LIVE) { // 活体
                    Log.e(TAG, "活体!");
                    displayToast("活体!");
//                    singleDetectDelay();

                    synchronized (cwLiveImage) { // TODO mwb
                        mLiveDetectImage.setImage(new CWLDImage(cwLiveImage.getData(),
                                cwLiveImage.getWidth(),
                                cwLiveImage.getHeight(),
                                CWDefine.CWEnumCameraDataFormat.values()[cwLiveImage.getFormat()],
                                false), false);

                        mDisplayImage.setImage(mLiveDetectImage);
                        CWLDImage cameraImage = null;
                        synchronized (mDisplayImage) {
                            if (null != mDisplayImage.getData()) {
                                cameraImage = mDisplayImage.clone();
                            }
                        }

                        if (cameraImage == null) {
                            displayToast("请先提取人脸照或活体人脸照");
                            return;
                        }

                        CWRet<CWFeature> cwRet = mEngine.getFeature(cameraImage, null, false);
                        if (!checkCWRetSucc(cwRet)
                                || cwRet.obj == null
                                || cwRet.obj.getRecogInfo() == null
                                || cwRet.obj.getRecogInfo().getFeature_data() == null
                                || cwRet.obj.getFaceRect() == null
                                || cwRet.obj.getFaceRect().size() <= 0
                                || cwRet.obj.getFaceNum() <= 0) {
                            displayToast("提取人脸照特征失败");
                            return;
                        }

                        byte[] feature = cwRet.obj.getRecogInfo().getFeature_data();
                        String fea = Change.bytesToHex(feature);
                        LogUtil.e("face:" + fea);

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "识别成功", Toast.LENGTH_SHORT).show();
                            }
                        });


//                        // TODO MWB 需要对比人脸
//                        synchronized (lockLiveDetect) {
//                            if (ErrorCode.CW_FACE_LIV_IS_LIVE == errorCode
//                                    && cwDetectorCallbackData.getLiveDetectData().getArrLivenessInformation().length > 0
//                                    && cwDetectorCallbackData.getLiveDetectData().getArrFaceInformation().length > 0) {
//                                mLiveDetectImage.setImage(new CWLDImage(cwLiveImage.getData(),
//                                        cwLiveImage.getWidth(),
//                                        cwLiveImage.getHeight(),
//                                        CWDefine.CWEnumCameraDataFormat.values()[cwLiveImage.getFormat()],
//                                        false), false);
//                                mLiveDetectRect.setFaceRect(cwDetectorCallbackData.getLiveDetectData().getArrFaceInformation()[0].getRect());
//                            }
//                            lockLiveDetect.notify();
//                        }

//                        contrastFace();
                    }


                } else { // 活检异常
                    int finalErrorCode = Long.valueOf(errorCode).intValue();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            showLiveResult(finalErrorCode);
                        }
                    });
                    singleDetectDelay();
                }

//                LogUtil.e("活检：" + errorCode);
                break;
            }
        }
    };

    //左眉遮挡
    public static final int CW_FACE_LIV_LEFT_EYEBROW_OCCLUSION_ERR = 26123000;
    //右眉遮挡
    public static final int CW_FACE_LIV_TIGHT_EYEBROW_OCCLUSION_ERR = 26123001;
    //左眼遮挡
    public static final int CW_FACE_LIV_LEFT_EYE_OCCLUSION_ERR = 26123002;
    //右眼遮挡
    public static final int CW_FACE_LIV_RIGHT_EYE_OCCLUSION_ERR = 26123003;
    //鼻子遮挡
    public static final int CW_FACE_LIV_NOSE_OCCLUSION_ERR = 26123004;
    //嘴巴遮挡
    public static final int CW_FACE_LIV_MOUTH_OCCLUSION_ERR = 26123005;

    /**
     * Show the result of the liveness
     *
     * @param errorCode
     */
    private void showLiveResult(int errorCode) {
        switch (errorCode) {
            case ErrorCode.CW_FACE_LIV_IS_LIVE:
                displayToast("活体");
                break;
            case ErrorCode.CW_FACE_LIV_IS_UNLIVE_ERR:
                displayToast("非活体");
                break;
            case ErrorCode.CW_FACE_LIV_DIST_TOO_FAR_ERR:
                displayToast("请离近一点");
                break;
            case ErrorCode.CW_FACE_LIV_DIST_TOO_CLOSE_ERR:
                displayToast("请离远一点");
                break;
            case ErrorCode.CW_FACE_LIV_POSE_DET_FAIL_ERR:
            case ErrorCode.CW_FACE_LIV_SKIN_FAILED_ERR:
            case ErrorCode.CW_FACE_LIV_NO_PAIR_FACE_ERR:
            case ErrorCode.CW_FACE_LIV_NIS_NO_FACE_ERR:
            case ErrorCode.CW_FACE_LIV_VIS_NO_FACE_ERR:
            case ErrorCode.CW_FACE_LIV_FACE_CLARITY_DET_FAIL_ERR:
            case ErrorCode.CW_FACE_LIV_VIS_BRIGHTNESS_EXC_ERR:
            case ErrorCode.CW_FACE_LIV_VIS_BRIGHTNESS_INS_ERR:
            case ErrorCode.CW_FACE_LIV_VIS_FACE_LOW_CONF_ERR:
            case ErrorCode.CW_FACE_QUALITY_DEFAULT:
            case ErrorCode.CW_FACE_NO_FACE:
            case CW_FACE_LIV_VIS_PUPIL_DIS_ERR:
            case CW_FACE_LIV_DEPTH_INTEGRITY_ERR:
                displayToast("请正对摄像头,保持人脸清晰");
                break;
            case ErrorCode.CW_FACE_LIV_VIS_EYE_CLOSE_ERR:
                displayToast("请睁眼");
                break;
            case ErrorCode.CW_FACE_LIV_VIS_MOUTH_OPEN_ERR:
                displayToast("请不要张嘴");
                break;
            case ErrorCode.CW_FACE_LIV_VIS_OCCLUSION_ERR:
                displayToast("请不要遮挡您的脸部");
                break;
            case ErrorCode.CW_FACE_LIV_VIS_BLACKSPEC_ERR:
                displayToast("请取下您的眼镜");
                break;
            case ErrorCode.CW_FACE_LIV_VIS_SUNGLASS_ERR:
                displayToast("请取下您的墨镜");
                break;
            case ErrorCode.CW_FACE_LIV_VIS_PROCEDUREMASK_ERR:
                displayToast("请摘下您的口罩");
                break;
            case CW_FACE_LIV_RIGHT_EYE_OCCLUSION_ERR:
                displayToast("右眼被遮挡");
                break;
            case CW_FACE_LIV_LEFT_EYE_OCCLUSION_ERR:
                displayToast("左眼被遮挡");
                break;
            case CW_FACE_LIV_NOSE_OCCLUSION_ERR:
                displayToast("鼻子被遮挡");
                break;
            case CW_FACE_LIV_MOUTH_OCCLUSION_ERR:
                displayToast("嘴巴被遮挡");
                break;
            case CW_FACE_LIV_LEFT_EYEBROW_OCCLUSION_ERR:
                displayToast("左眉毛被遮挡");
                break;
            case CW_FACE_LIV_TIGHT_EYEBROW_OCCLUSION_ERR:
                displayToast("右眉毛被遮挡");
                break;
            case CW_LIVENESS_MULTI_FACE_ERROR:
                displayToast("检测到多张人脸");
                break;
            default:
                break;
        }
    }

    /**
     * un-initialize
     */
    private void releaseEngine() {
        mWorkHandler.post(() -> {
            mEngine.unInit();
        });
    }

    /**
     * 延时活检
     */
    private void singleDetectDelay() {
        mWorkHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                singleDetect();
            }
        }, 1000);
    }

    /**
     * 人脸特征长度
     */
    private int featureLength = 0;

    /**
     * 人脸对比 TODO MWB
     */
    private void contrastFace(byte[] mLibFeatures) {
        mWorkHandler.post(() -> {
            CWLDImage mRecognizeCameraImage = mDisplayImage.clone();
            CWFaceRect mRecognizeFaceRect;

            mRecognizeFaceRect = mLiveDetectRect.clone();

            synchronized (faceRecognizeLock) {
                if (featureLength == 0) {
                    featureLength = mEngine.getFeatureLength().obj;
                }

                float maxScore = getMaxRecognizeScore(mRecognizeCameraImage, mRecognizeFaceRect, mLibFeatures, 1);
            }
        });
    }


    /**
     * Get max recog score
     *
     * @param mCurrentImage
     * @param cwFaceRect
     * @return
     */
    private float getMaxRecognizeScore(CWLDImage mCurrentImage, CWFaceRect cwFaceRect, byte[] mLibFeatures, int mlibSize) {

        if (mCurrentImage == null || cwFaceRect == null) {
            return 0;
        }

        // 获取当前人脸图片
        CWRet<CWFeature> cwRet = mEngine.getFeature(mCurrentImage, cwFaceRect, false);
        if (!checkCWRetSucc(cwRet) || null == cwRet.obj) {
            LogUtil.e("获取人脸特征失败 ErrorCode: " + cwRet.errorCode);
            return 0;
        }
        CWRecogInfo cwRecogInfo = cwRet.obj.getRecogInfo();
        //Get lib from disk
        if (mLibFeatures != null && mlibSize > 0) {
            //Compare
            CWRet<float[]> cwRet1 = mEngine.compareFeature(cwRecogInfo.getFeature_data(), mLibFeatures, mlibSize);
            if (!checkCWRetSucc(cwRet1) || cwRet1.obj == null) {
                LogUtil.e("比对失败");
                return 0;
            }
            float[] mRecogScores = cwRet1.obj;
            //Get max score
            float maxScore = 0.0f;
            for (int i = 0; i < mRecogScores.length; i++) {
                if (mRecogScores[i] > maxScore) {
                    maxScore = mRecogScores[i];
                }
            }
            return maxScore;
        }
        return 0;
    }

    @Override
    protected void onDestroy() {
        stopContinuityDetect();
        closeCamera();
        releaseEngine();
        mEngine.addEngineInterfaceCallListener(null);

//        if (mWorkHandler != null) { 会内存溢出
//            mWorkHandler.removeCallbacksAndMessages(null);
//        }
        mWorkThread.quitSafely();
        super.onDestroy();

    }
}